package cn.kmsoft.jssc.controller;


//import cn.kmsoft.common.ResInfoEx;
//import cn.kmsoft.common.ResultEnum;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.gistool.util.JTSGeometryOperations;
import cn.kmsoft.jssc.config.RabbitMqConfig;
import cn.kmsoft.jssc.entity.analyse.CustomOverlay;
import cn.kmsoft.jssc.entity.analyse.DetailResult;
import cn.kmsoft.jssc.entity.analyse.DlhyAnalyseParam;
import cn.kmsoft.jssc.entity.analyse.DltbDetailResult;
import cn.kmsoft.jssc.entity.dlhy.DlhyEntity;
import cn.kmsoft.jssc.entity.mq.JsscMqMessage;
import cn.kmsoft.jssc.entity.mq.MqMessage;
import cn.kmsoft.jssc.service.impl.DlhyServiceImpl;
import cn.kmsoft.common.DebugMsgInfo;
import cn.kmsoft.common.ResInfo;

import cn.kmsoft.stgeometry.landm.StgeoFeature;
import cn.kmsoft.stgeometry.landm.StgeoFeature2;
import cn.kmsoft.stgeometry.util.*;
import cn.kmsoft.wololo.object.GeoJson;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.SchemaException;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static cn.kmsoft.common.ResInfo.failed;

@Slf4j
@Component
@RestController
@Api(description = "地类还原", tags = "5-DlhyController")
@RequestMapping(value = "/dlhy")
public class DlhyController extends BaseController {
    //private static final Logger logger = LoggerFactory.getLogger(DlhyController.class);

    private final double areaScale = 10000;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss-SSS");

    private final PythonApi pythonApi;

    private final DlhyServiceImpl dlhyService;

    @Autowired
    private AmqpTemplate rabbitTemplate;//rabbitmq消息队列


    @Autowired
    public DlhyController(PythonApi pythonApi, DlhyServiceImpl dlhyService) {
        this.pythonApi = pythonApi;
        this.dlhyService = dlhyService;
    }

    @ApiOperation(value = "地类还原分析测试", notes = "土地利用现状空间套合分析，直接进行调用spatialboot进行空间分析，不检查dltb是否修改")
    @RequestMapping(value = "/dlhyAnalyseTest", method= RequestMethod.GET)
    public ResInfo dlhyAnalyseTest(String projectId ){
        ResInfo resInfo = new ResInfo();

        Date dateNow=new Date();
        String dtimeNowStr= sdf.format(dateNow);
        String startMsgStr = String.format("--->步骤0，dlhyAnalyseTest started,projectId: %s ,startTime: %s",projectId, dtimeNowStr);
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        //3-shp2geoquery
        //1-测试数据的导入
        //String shppath ="E:\\temp\\jssc\\500155梁平区\\01空间数据\\变化图斑.shp";
        String shppath = this.analyseConfig.getTestshppath();
        int wkid = 4524;
        try {
            String crsName = JTSGeometryWKTUtil.getShpCrsName(shppath);
            String wkidStr = CrsUtil.getWkidByCrsName(crsName);//动态获取坐标投影srid
            wkid = Integer.parseInt(wkidStr);
        } catch (Exception e) {
            e.printStackTrace();
        }


        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(shppath, wkid);
        GeoJsonQuery geoJsonQuery= GeoJsonQueryUtil.shp2GeoQuery(shppath, wkid);

        DlhyAnalyseParam dlhyAnalyseParam= new DlhyAnalyseParam();
        dlhyAnalyseParam.setTaskId(projectId);
        dlhyAnalyseParam.setGeoJsonQuery(geoJsonQuery);
        dlhyAnalyseParam.setPhase(dtimeNowStr);

        //地类还原
        List<CustomOverlay> cusOverlayList = this.dlhyService.overlayDlhy("1111111111",dlhyAnalyseParam);
        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setCode(200);
        resInfo.setMsg("dlhyAnalyseTest success! ");
        resInfo.setRes(cusOverlayList);

        return resInfo;
    }

    @ApiOperation(value = "地类还原分析测试2", notes = "土地利用现状空间套合分析，空间分析采用opengis库完成")
    @RequestMapping(value = "/dlhyAnalyseTest2", method= RequestMethod.GET)
    public ResInfo dlhyAnalyseTest2(String projectId ){
        ResInfo resInfo = new ResInfo();

        Date dateNow=new Date();
        String dtimeNowStr= sdf.format(dateNow);
        String startMsgStr = String.format("--->步骤0，dlhyAnalyseTest2 started,projectId: %s ,startTime: %s",projectId, dtimeNowStr);
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        //3-shp2geoquery
        String ydhxfw_path = "E:\\temp\\jssc\\500155梁平区\\01空间数据\\用地红线范围.shp";
        String bhtb_path = "E:\\temp\\jssc\\500155梁平区\\01空间数据\\变化图斑.shp";
        String qsjx_path = "E:\\temp\\jssc\\500155梁平区\\01空间数据\\权属界线.shp";
        String dltb_path = "E:\\temp\\jssc\\500155梁平区\\01空间数据\\地类图斑.shp";
        String bhtb01_path="E:\\temp\\jssc\\500155梁平区\\01空间数据\\变化图斑01.shp";
        int wkid = 4524;
        try {
            String crsName = JTSGeometryWKTUtil.getShpCrsName(ydhxfw_path);
            String wkidStr = CrsUtil.getWkidByCrsName(crsName);//动态获取坐标投影srid
            wkid = Integer.parseInt(wkidStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(shppath, wkid);

        //获取BHDM=1的还原地类图斑（bhdm=1）
        String targetFieldName = "BHDM";
        String targetFieldVal = "1";//变化代码
        Map<String,String> properties = JTSGeometryWKTUtil.getYwPropertieSchemas(bhtb_path);
        Map<String, StgeoFeature> stgeoFeatureMap = JTSGeometryWKTUtil.getHydltbShpByFilter(bhtb_path,targetFieldName,targetFieldVal);

        String taskId = projectId;
        try {
            this.dlhyService.saveStgeoFeatureAsNewSHP(taskId, wkid, stgeoFeatureMap,properties,bhtb01_path);
            //JTSGeometryOperations.spatialDifference(ydhxfw_path,"","","utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.shp2GeoQuery(bhtb_path, wkid);

        DlhyAnalyseParam dlhyAnalyseParam= new DlhyAnalyseParam();
        dlhyAnalyseParam.setTaskId(projectId);
        dlhyAnalyseParam.setGeoJsonQuery(geoJsonQuery);
        dlhyAnalyseParam.setPhase(dtimeNowStr);

        //地类还原
        List<CustomOverlay> cusOverlayList = this.dlhyService.overlayDlhy(taskId,dlhyAnalyseParam);
        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setCode(200);
        resInfo.setMsg("dlhyAnalyseTest success! ");
        resInfo.setRes(cusOverlayList);

        return resInfo;
    }

    @ApiOperation(value = "地类还原分析测试30", notes = "土地利用现状空间套合分析，空间分析采用调用arcpy来完成，数据筛选和叠加全部采用java")
    @RequestMapping(value = "/dlhyAnalyseTest30", method= RequestMethod.GET)
    public ResInfo dlhyAnalyseTest30(String projectId ) {
        ResInfo resInfo = new ResInfo();
        int wkid = 4524;

        Date dateNow = new Date();
        String dtimeNowStr= sdf.format(dateNow);
        String startMsgStr = String.format("--->步骤0，dlhyAnalyseTest30 started,projectId: %s ,startTime: %s",projectId, dtimeNowStr);
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        //步骤2、3
        //this.pythonApi.doJsscDlhyAnalyst(taskId,"jsscDataHandle");
        String bhtb_path = "E:\\temp\\jssc\\500155\\01空间数据\\变化图斑.shp";
        String ydhxfw_path = "E:\\temp\\jssc\\500155\\01空间数据\\用地红线范围.shp";

        try {
            //获取BHDM=1的还原地类图斑（bhdm=1）
            String targetFieldName = "BHDM";
            String targetFieldVal = "1";//变化代码
            Map<String,String> properties = JTSGeometryWKTUtil.getYwPropertieSchemas(bhtb_path);
            Map<String, StgeoFeature> stgeoFeatureMap = JTSGeometryWKTUtil.getHydltbShpByFilter(bhtb_path,targetFieldName,targetFieldVal);

            try {
                String bhtb01_path = "E:\\temp\\jssc\\500155\\temp\\out_bhtb01.shp";
                this.dlhyService.saveStgeoFeatureAsNewSHP(projectId,wkid,stgeoFeatureMap,properties,bhtb01_path);
                //JTSGeometryOperations.spatialDifference(ydhxfw_path,"","","utf-8");
            } catch (Exception e) {
                e.printStackTrace();
            }


            //筛选BHDM=1的图斑
            String bhtb01_jsonStr = this.selectBhtbAsGeoJsonStr(bhtb_path);
            String ydhxfw_jsonStr = Shapefile2GeoJson.shp2GeoJsonStr1(ydhxfw_path);
            //扣除BHDM=1的图斑后的用地红线范围
            String ydhxfw_diff_jsonStr = this.diffBhtbAsJsonStr(ydhxfw_jsonStr, bhtb01_jsonStr);


            String analyseType = "bgdc";
            List<DlhyEntity> dlhyEntityList01 = this.dlhyAnalyseEx(projectId, analyseType, wkid, ydhxfw_diff_jsonStr);
            analyseType = "dlhy";
            List<DlhyEntity> dlhyEntityList02 = this.dlhyAnalyseEx(projectId, analyseType,wkid, bhtb01_jsonStr);

            //4-合并地类还原成果
            String bhtbmerge_resultpath = "E:\\temp\\jssc\\500155\\temp\\std_dltb_merge2.shp";
            //List<DlhyEntity>  dlhyEntityListMerge = Lists.newArrayList(Iterables.concat(dlhyEntityList01,dlhyEntityList02));
            List<DlhyEntity>  dlhyEntityListMerge = ListUtils.union(dlhyEntityList01,dlhyEntityList02);
            try {
                this.dlhyService.saveDlhyListAsNewSHP(projectId,wkid,dlhyEntityListMerge,bhtbmerge_resultpath);
            } catch (SchemaException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //this.pythonApi.doJsscDlhyAnalyst(taskId,"jsscDlhyAnalyst");

        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setCode(200);
        resInfo.setMsg("dlhy AnalyseTest success! ");
        resInfo.setRes("");

        return resInfo;
    }

    @ApiOperation(value = "地类还原分析测试31", notes = "土地利用现状空间套合分析，空间分析采用调用arcpy来完成，优化了地类还原代码")
    @RequestMapping(value = "/dlhyAnalyseTest31", method= RequestMethod.GET)
    public ResInfo dlhyAnalyseTest31(String taskId ) {
        ResInfo resInfo = new ResInfo();
        List<DebugMsgInfo> results = new ArrayList<DebugMsgInfo>();
        Date dateNow = new Date();
        String startTimeStr = sdf.format(dateNow);

        String msgStr = String.format("--->步骤0，dlhyAnalyseTest31 started, taskId: %s , times: %s ",taskId, startTimeStr );
        DebugMsgInfo msg1=new DebugMsgInfo(1,msgStr);
        results.add(msg1);
        System.out.println(msg1);
        log.info(msgStr);

        //步骤2、3 发送数据处理消息到后台arcpy中
        this.pythonApi.doJsscDlhyAnalyst(taskId,"jsscDataHandle");
        String process01_msg = String.format("--->步骤1已完成,jsscDataHandle");
        DebugMsgInfo msg2=new DebugMsgInfo(2,process01_msg);
        System.out.println(msg2);
        results.add(msg2);
        log.info(process01_msg);

        //3-地类还原
        String ydhxfw_path = this.analyseConfig.getDlhyOriginalFolder() + File.separator + taskId + File.separator + "temp" + File.separator + "out_ydhxfw_earse.shp";
        String bhtb01_path = this.analyseConfig.getDlhyOriginalFolder() + File.separator + taskId + File.separator + "temp" + File.separator + "qx_bhtb_01.shp";
        if(this.profilesActive.equalsIgnoreCase("dev")) {
            ydhxfw_path = "E:\\temp\\jssc\\500155\\temp\\out_ydhxfw_earse.shp";
            bhtb01_path = "E:\\temp\\jssc\\500155\\temp\\qx_bhtb_01.shp";
        }
        File ydhxfw_earse_file = new File(ydhxfw_path);
        File qx_bhtb_01_file = new File(bhtb01_path);
        if( !ydhxfw_earse_file.exists() || !qx_bhtb_01_file.exists() ){
            String errorMsg = "--->输入数据异常，out_ydhxfw_earse或qx_bhtb_01 为空";
            resInfo.setMsg(errorMsg);
            log.error(errorMsg);

            DebugMsgInfo msg3 = new DebugMsgInfo(3,errorMsg);
            results.add(msg3);

            String input_filePath= String.format("---inputs ydhxfw_path: %s, bhtb01_path: %s",ydhxfw_path,bhtb01_path);
            DebugMsgInfo msg4= new DebugMsgInfo(4,input_filePath);
            results.add(msg4);

            resInfo.setRes(results);
            resInfo.setData(null);
            resInfo.setStatus(ResInfo.FAIL);
            resInfo.setCode(200);

            return resInfo;
        }

        //4-坐标系解析
        int wkid = 4524;
        try {
            String crsName = JTSGeometryWKTUtil.getShpCrsName(ydhxfw_path);
            String wkidStr = CrsUtil.getWkidByCrsName(crsName);//动态获取坐标投影srid
            wkid = Integer.parseInt(wkidStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String analyseType = "bgdc";
        List<DlhyEntity> dlhyEntityList01 =this.dlhyAnalyseEx(taskId, analyseType, wkid, ydhxfw_path);

        analyseType = "dlhy";
        List<DlhyEntity> dlhyEntityList02 =this.dlhyAnalyseEx(taskId, analyseType,wkid, bhtb01_path);

        //6-合并地类还原成果
        String bhtbmerge_resultpath = this.analyseConfig.getDlhyOriginalFolder() + File.separator + taskId + File.separator + "temp" + File.separator + "std_dltb_merge.shp";
        if(this.profilesActive.equalsIgnoreCase("dev")) {
            bhtbmerge_resultpath = "E:\\temp\\jssc\\500155\\temp\\std_dltb_merge.shp";
        }
        //List<DlhyEntity>  dlhyEntityListMerge = Lists.newArrayList(Iterables.concat(dlhyEntityList01,dlhyEntityList02));
        List<DlhyEntity>  dlhyEntityListMerge = ListUtils.union(dlhyEntityList01,dlhyEntityList02);
        String msgInfo3 = String.format("--->步骤2已完成, 获取的dlhyEntityListMerge：%d,其中bgdc：%d, dlhy: %d  ",dlhyEntityListMerge.size(),dlhyEntityList01.size(), dlhyEntityList02.size());
        System.out.println(msgInfo3);
        log.info(msgInfo3);

        DebugMsgInfo msg3=new DebugMsgInfo(4,msgInfo3);
        results.add(msg3);


        try {
            this.dlhyService.saveDlhyListAsNewSHP(taskId,wkid,dlhyEntityListMerge,bhtbmerge_resultpath);
        } catch (Exception e) {
            String exceptionMsg = e.getMessage();
            String errorMsg = String.format("--->步骤2，saveDlhyListAsNewSHP error, taskId: %s, exceptionMsg: %s",taskId, exceptionMsg);
            log.error(errorMsg);
            System.out.println(errorMsg);
        }

        //7-结果叠加分析
        this.pythonApi.doJsscDlhyAnalyst(taskId,"jsscDlhyAnalyst");
        String msgInfo4 = String.format("--->步骤3已完成,jsscDlhyAnalyst");
        log.info(msgInfo4);
        System.out.println(msgInfo4);

        DebugMsgInfo msg4 = new DebugMsgInfo(5,msgInfo4);
        results.add(msg4);


        Date enddateNow = new Date();
        String endTimeStr = sdf.format(enddateNow);
        String msgInfo5 = String.format("--->dlhyAnalyseTest31 finished, taskId: %s , times: %s ",taskId, endTimeStr );
        log.info(msgInfo5);

        DebugMsgInfo msg5=new DebugMsgInfo(6,msgInfo5);
        results.add(msg5);
        System.out.println(msg5);


        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setCode(200);
        resInfo.setMsg("dlhy AnalyseTest finished! ");
        resInfo.setRes(results);

        return resInfo;
    }

    @ApiOperation(value = "数据预处理分析", notes = "第一步，发送消息调用arcpy来，开展变化图斑筛选、权属界线Dissolve等工作")
    @RequestMapping(value = "/dlhyPreHandle", method= RequestMethod.GET)
    public ResInfo dlhyPreHandle(String projectId ) {
        ResInfo resInfo = new ResInfo();
        List<DebugMsgInfo> results = new ArrayList<DebugMsgInfo>();
        String jobId = projectId;

        Date dateNow = new Date();
        String startTimeStr = sdf.format(dateNow);

        System.out.println();
        System.out.println();
        String msgStr = String.format("************ 第一步，dlhyPreHandle submit, projectId: %s , times: %s ********************",projectId, startTimeStr );
        System.out.println(msgStr);
        log.info(msgStr);

        DebugMsgInfo msg1=new DebugMsgInfo(1, msgStr);
        results.add(msg1);

        //核心代码
        this.sendMqQsjxDissolve(jobId);

        resInfo.setCode(200);
        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setMsg(msgStr);
        resInfo.setRes(results);

        return resInfo;
    }

    @ApiOperation(value = "开始执行地类还原分析", notes = "地类还原分析，后台采用arcpy+st_geometry来完成分析，借助消息队列进行业务串联，异步完成")
    @GetMapping(value = "/{zipFilename}/analysis")
    public ResInfo doDlhyExecute(@PathVariable String zipFilename) {
        ResInfo resInfo = new ResInfo();
        List<DebugMsgInfo> results = new ArrayList<DebugMsgInfo>();
        Date dateNow = new Date();
        String startTimeStr = sdf.format(dateNow);

        System.out.println();
        System.out.println("############################jssc receive dlhy request,收到地类还原分析请求##################################");
        String msgStr = String.format("--->dlhyAnalyseTest32 started, projectId: %s , times: %s ",zipFilename, startTimeStr );
        //System.out.println(msgStr);
        log.info(msgStr);

        DebugMsgInfo msg1 = new DebugMsgInfo(1,msgStr);
        results.add(msg1);

        //步骤2、3
        //地类还原，发送数据处理的命令
        //向消息队列JAVA2ARCPY_JSSC_ROUTINGKEY中发生JsscMqMessage.OPERCODE_DATA_HANDLE（10002）指令到arcpy后台
        //10002
        this.sendMqDljyDataHandle(zipFilename);

        resInfo.setStatus(ResInfo.SUCCESS);
        resInfo.setCode(200);
        resInfo.setMsg(msgStr);
        resInfo.setRes(results);

        return resInfo;
    }

    /**
     * 核心代码，特色亮点之处
     * 消息队列响应函数   这里订阅接收arcpy处理后发出的消息，消息队列的RabbitMqConfig.AECPY2JAVA_JSSC_QUEUE消息
     * @param msg
     */
    @RabbitListener(queues = RabbitMqConfig.AECPY2JAVA_JSSC_QUEUE)
    @RabbitHandler
    public void onJsscMqListenerHandler(Message msg){
        String msgStr = new String(msg.getBody());
        System.out.println();
        System.out.println("****************************onJsscMqListenerHandler.AECPY2JAVA_JSSC_QUEUE************************");
        System.out.println(msgStr);

        try {
            //判断str是否为json字符串
            if(StringUtil.isJSONType(msgStr)) {
                //MqMessage mqMsg = JSONObject.parseObject(msgStr, MqMessage.class);
                JsscMqMessage mqMsg = JSONObject.parseObject(msgStr, JsscMqMessage.class);
                String jobId = mqMsg.getJobId();//任务编号，uuid
                int operatorCode = mqMsg.getOperationCode();
                switch (operatorCode){
                    case JsscMqMessage.OPERCODE_RABBITMQ_TEST:
                    {
                        //消息队列ping、pong测试
                        String rabbitmq_pong_msg = String.format("--->0.arcpy2java receive rabbitmq pong, operation_code=99999，jobId: %s, msg：",jobId, mqMsg.toString());
                        System.out.println();
                        //System.out.println(rabbitmq_pong_msg);
                        log.info(rabbitmq_pong_msg);

                        //说明：rabbitmq通信正常或者arcpy能收到java端的消息
                        //收到本消息，立即将statusCode重置为0；
                        this.updRabbitMQStatus(jobId,0);
                        break;
                    }
                    case JsscMqMessage.OPERCODE_ERROR_ACKPY:
                    {
                        String process_msg=String.format("--->1.arcpy2java jssc arcpy error,set operation_code=10000，jobId: %s, msg：",jobId,mqMsg.toString());
                        System.out.println();
                        //System.out.println(process_msg);
                        log.info(process_msg);

                        //arcpy后台发生异常，终止运算
                        this.setJsscStatusByProjectId(jobId,"10000");
                        break;
                    }
                    case JsscMqMessage.OPERCODE_QSJX_DISSOLVE:
                    {
                        String process_msg=String.format("--->1.arcpy2java jssc qsjx dissolve finished，jobId: %s, msg：",jobId,mqMsg.toString());

                        System.out.println();
                        //System.out.println(process_msg);
                        log.info(process_msg);

                        //arcpy后台开展数据dissolve数据预处理已完成
                        //设置10001标识
                        this.setJsscStatusByProjectId(jobId,"10001");

                        //下一步，要干啥呢
                        //由前端发起dlhyAnalyseTest32请求

                        break;
                    }
                    case JsscMqMessage.OPERCODE_DATA_HANDLE:
                    {
                        int failedCode = -1;
                        //2-数据预处理完成，开始地类还原分析
                        System.out.println();
                        System.out.println("***************************************2-OPERCODE_DATA_HANDLE 数据预处理完成，开始地类还原分析*******************************");
                        String process01_msg = String.format("--->步骤1已完成,arcpy2java, jsscDataHandle,jobId: %s",jobId);
                        //System.out.println(process01_msg);
                        log.info(process01_msg);

                        //后台arcpy数据预处理工作已完成,设置状态值为10002
                        this.setJsscStatusByProjectId(jobId,"10002");

                        String ydhxfw = this.analyseConfig.getDlhyOriginalFolder()
                                + File.separator + jobId
                                + File.separator + "01空间数据"
                                + File.separator + "用地红线范围.shp";

                        //3-地类还原
                        String ydhxfw_path_erase = this.analyseConfig.getDlhyOriginalFolder()
                                + File.separator + jobId
                                + File.separator + "temp"
                                + File.separator + "out_ydhxfw_earse.shp";
                        String bhtb01_path = this.analyseConfig.getDlhyOriginalFolder()
                                + File.separator + jobId
                                + File.separator + "temp"
                                + File.separator + "qx_bhtb_01.shp";
                        String qx_dltb_lt2009 = this.analyseConfig.getDlhyOriginalFolder()
                                + File.separator + jobId
                                + File.separator + "temp"
                                + File.separator + "qx_dltb_lt2009.shp";
                        if(this.profilesActive !=null && this.profilesActive.equalsIgnoreCase("dev")) {
                            ydhxfw_path_erase = "E:\\temp\\jssc\\500155\\temp\\out_ydhxfw_earse.shp";
                            bhtb01_path = "E:\\temp\\jssc\\500155\\temp\\qx_bhtb_01.shp";
                        }
                        File ydhxfw_earse_file = new File(ydhxfw_path_erase);
                        File qx_bhtb_01_file = new File(bhtb01_path);
                        //拼装的数据路径不存在
                        if( !ydhxfw_earse_file.exists() || !qx_bhtb_01_file.exists() ){
                            String errorMsg= String.format("--->步骤2，输入shp数据异常，out_ydhxfw_earse或qx_bhtb_01 为空。inputs ydhxfw_path: %s, bhtb01_path: %s", ydhxfw_path_erase, bhtb01_path);
                            //System.out.println(errorMsg);
                            log.error(errorMsg);

                            failedCode = 1;
                        }

                        //4-坐标系解析
                        int wkid = 4524;
                        String wkidStr="";
                        try {
                            String crsName = JTSGeometryWKTUtil.getShpCrsName(ydhxfw);
                            wkidStr= CrsUtil.getWkidByCrsName(crsName);
                            wkid = Integer.parseInt(wkidStr);
                        } catch (Exception e) {
                            failedCode=2;
                            String errorWkidMsg= String.format("--->步骤2，解析shp坐标投影信息异常, ydhxfw_path: %s, wkidStr: %s",ydhxfw_path_erase,wkidStr);
                            //System.out.println(errorWkidMsg);
                            log.error(errorWkidMsg);

                            e.printStackTrace();
                        }

                        //5-执行java端地类还原分析
                        /**
                         *  地类还原的核心代码，执行地类还原有三个过程，
                         *  第一个过程：qxsb-在变化图斑中，筛选出2009年以前的qx_dltb_lt2009.shp，用来和区县上传的地类图斑进行叠加分析。
                         *  第二个过程：bgdc-在变化图斑中筛选2009年及以后的图斑(qx_dltb_ge2009.shp)中筛选BHDM=1的，形成qx_bhtb_01.shp，扣除BHDM=1后和qx_dltb_lt2009之后形成用地红线范围out_ydhxfw_earse.shp，用BZ字段对应的变更调查进行分析。
                         *  第二个过程：dlhy-用BHDM=1的变化图斑形成qx_bhtb_01.shp，与HYSJND对应年份的地类图斑进行地类还原
                         */
                        try {
                            System.out.println();
                            //步骤2-1, 变化图斑图层的HYSJND中在2009以前的，直接使用区县上传的地类图斑成果
                            String dlhyFxlx = "qxsb";
                            File qxdltb_lt2009_file = new File(qx_dltb_lt2009);

                            List<DlhyEntity> dlhyEntityList00=null;
                            int sizeOfQxsb = 0;//区县上报的个数
                            if( qxdltb_lt2009_file.exists()) {
                                dlhyEntityList00 = this.dlhyAnalyseEx(jobId, dlhyFxlx, wkid, qx_dltb_lt2009);//2009年之前的用地范围图斑*区县上传的地类图斑
                                sizeOfQxsb = dlhyEntityList00 != null ? dlhyEntityList00.size() : 0;
                                String zjsyMsgInfo = String.format("--->步骤2-1，jobId: %s, dlhyAnalyseEx 已完成, dlhyFxlx：%s, 获取的dlhyEntityList01：%d", jobId, dlhyFxlx, sizeOfQxsb);
                                //System.out.println(zjsyMsgInfo);
                                log.info(zjsyMsgInfo);

                            }else {
                                String detailmsg=String.format("--->步骤2-1，jobId: %s, qxdltb_lt2009_file: %s 不存在",jobId,qx_dltb_lt2009);
                                //System.out.println(detailmsg);
                                log.error(detailmsg);
                            }

                            //步骤2-2，使用用地红线范围图层的BZ字段
                            dlhyFxlx = "bgdc";
                            List<DlhyEntity> dlhyEntityList01 = this.dlhyAnalyseEx(jobId, dlhyFxlx, wkid, ydhxfw_path_erase);//扣减后的用地范围红线
                            int sizeOfBgdc = dlhyEntityList01 != null ? dlhyEntityList01.size() : 0;
                            if(sizeOfBgdc>0) {
                                String bgdcMsgInfo = String.format("--->步骤2-2，jobId: %s, dlhyAnalyseEx 已完成, dlhyFxlx：%s, 获取的dlhyEntityList01：%d", jobId, dlhyFxlx, sizeOfBgdc);
                                //System.out.println(bgdcMsgInfo);
                                log.info(bgdcMsgInfo);
                            }

                            //步骤2-3，使用变化图斑图层的HYSJND字段
                            dlhyFxlx = "dlhy";
                            List<DlhyEntity> dlhyEntityList02 =this.dlhyAnalyseEx(jobId, dlhyFxlx, wkid, bhtb01_path);//2009年之后的且BHDM=1的部分变化图斑
                            int sizeOfDlhy = dlhyEntityList02 != null ? dlhyEntityList02.size() : 0;
                            if(sizeOfDlhy>0) {
                                String dlhyMsgInfo = String.format("--->步骤2-3，jobId: %s, dlhyAnalyseEx 已完成, dlhyFxlx：%s, 获取的dlhyEntityList02：%d", jobId, dlhyFxlx, sizeOfDlhy);
                                //System.out.println(dlhyMsgInfo);
                                log.info(dlhyMsgInfo);
                            }

                            //6-步骤2-4， 使用ListUtils.union合并 变更调查+地类还原 的分析成果
                            String bhtbmerge_resultpath = this.analyseConfig.getDlhyOriginalFolder() + File.separator + jobId + File.separator + "temp" + File.separator + "std_dltb_merge.shp";
                            if (this.profilesActive.equalsIgnoreCase("dev")) {
                                bhtbmerge_resultpath = "E:\\temp\\jssc\\500155\\temp\\std_dltb_merge.shp";
                            }

                            //先实现bhtb与dlhy的成果合并，然后在与qxsb的进行第二次合并
                            //List<DlhyEntity>  dlhyEntityListMerge = Lists.newArrayList(Iterables.concat(dlhyEntityList01,dlhyEntityList02));
                            List<DlhyEntity> dlhyEntityListMerge1=null;
                            if(dlhyEntityList01 !=null && dlhyEntityList02 != null){
                                //BGDC与DLHY联合
                                dlhyEntityListMerge1 = ListUtils.union(dlhyEntityList01, dlhyEntityList02);
                                int sizeOfAllMerge = dlhyEntityListMerge1 != null ? dlhyEntityListMerge1.size() : 0;
                                String msgInfo3 = String.format("--->步骤2-4-0，jobId: %s, dlhyAnalyseEx已完成, 获取的dlhyEntityListMerge, sizeOfAllMerge：%d, 其中 bgdc: %d, dlhy: %d  ", jobId, sizeOfAllMerge,  sizeOfBgdc, sizeOfDlhy);
                                System.out.println(msgInfo3);
                                log.info(msgInfo3);
                            }else{
                                if(dlhyEntityList01 !=null ){
                                    //bgdc
                                    dlhyEntityListMerge1 = dlhyEntityList01;
                                    String msgInfo3 = String.format("--->步骤2-4-1，jobId: %s, dlhyAnalyseEx已完成, dlhy为空,  bgdc: %d", jobId, sizeOfBgdc);
                                    System.out.println(msgInfo3);
                                    log.info(msgInfo3);
                                }
                                if(dlhyEntityList02 !=null ){
                                    //dlhy
                                    dlhyEntityListMerge1 = dlhyEntityList02;
                                    String msgInfo3 = String.format("--->步骤2-4-2，jobId: %s, dlhyAnalyseEx已完成, bgdc为空,  dlhy: %d", jobId, sizeOfDlhy);

                                    System.out.println(msgInfo3);
                                    log.info(msgInfo3);
                                }
                            }

                            int sizeOfAllMerge1 = dlhyEntityListMerge1.size();
                            List<DlhyEntity> dlhyEntityListMerge = dlhyEntityListMerge1;
                            if( dlhyEntityList00 !=null && sizeOfQxsb > 0) {
                                List<DlhyEntity> dlhyEntityListMerge2 = ListUtils.union(dlhyEntityListMerge1, dlhyEntityList00);
                                int sizeOfAllMerge2 = dlhyEntityListMerge2 != null ? dlhyEntityListMerge2.size() : 0;
                                String msgInfo4 = String.format("--->步骤2-5，jobId: %s, dlhyAnalyseEx已完成, dlhyEntityListMerge1与qxsb进行Union, allsize：%d,其中 qxsb: %d, sizeOfAllMerge1: %d  ", jobId, sizeOfAllMerge2, sizeOfQxsb, sizeOfAllMerge1);
                                //System.out.println(msgInfo4);
                                log.info(msgInfo4);

                                dlhyEntityListMerge = dlhyEntityListMerge2;
                            }

                            //7-保存结果为shp图层
                            try {
                                this.dlhyService.saveDlhyListAsNewSHP(jobId, wkid, dlhyEntityListMerge, bhtbmerge_resultpath);
                            } catch (Exception e) {
                                failedCode=3;

                                String errorStr="--->步骤2,saveDlhyListAsNewSHP error, msg: "+e.getMessage();
                                //System.out.println(errorStr);
                                log.error(errorStr);
                            }
                        }catch (Exception ex){
                            failedCode=3;

                            //ex.printStackTrace();
                            String msgInfo4 = String.format("--->步骤2,执行java端地类还原分析 error, msg: %s",ex.getMessage());
                            //System.out.println(msgInfo4);
                            log.error(msgInfo4);
                        }

                        if(failedCode >0) {
                            //java后台计算发生异常
                            String errorMsg= String.format("--->步骤2,执行java端地类还原分析过程中发生了异常，jobId: %s，failedCode: %d", jobId, failedCode);
                            //System.out.println(errorMsg);
                            log.info(errorMsg);
                            this.setJsscStatusByProjectId(jobId,"10000");
                        }else {
                            //很重要，发送地类还原数据分析的命令到arcpy，RabbitMqConfig.JAVA2ARCPY_JSSC_ROUTINGKEY
                            //10003
                            this.sendMqDlhyPostAnalyst(jobId);
                        }

                        break;
                    }
                    case JsscMqMessage.OPERCODE_DATA_ANALYST:
                    {
                        //将10003状态值写入redis数据库
                        this.setJsscStatusByProjectId(jobId,"10003");

                        String msgInfo4 = String.format("--->步骤3已完成, arcpy2java, jsscDlhyAnalyst,jobId: %s",jobId);
                        System.out.println();
                        //System.out.println(msgInfo4);
                        log.info(msgInfo4);

                        Date enddateNow = new Date();
                        String endTimeStr = sdf.format(enddateNow);
                        String msgInfo5 = String.format("--->dlhyAnalyseTest32 finished, jobId: %s , times: %s ",jobId, endTimeStr );
                        //System.out.println(msgInfo5);
                        log.info(msgInfo5);

                        break;
                    }

                    default: {
                        Date enddateNow = new Date();
                        String endTimeStr = sdf.format(enddateNow);
                        String msgInfo5 = String.format("--->dlhyAnalyseTest32 error, operatorCode is not found,jobId: %s , times: %s ", jobId, endTimeStr);
                        System.out.println();
                        //System.out.println(msgInfo5);
                        log.info(msgInfo5);

                    }
                        break;
                }

            }
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }

    /**
     * 在JAVA2ARCPY_JSSC_ROUTINGKEY中发送OPERCODE_QSJX_DISSOLVE消息，
     *     arcpy后台开展权属界线融合数据处理，完成后向AECPY2JAVA_JSSC_QUEUE发送OPERCODE_QSJX_DISSOLVE
     * @param jobId
     */
    public void sendMqQsjxDissolve(String jobId){
        //消息属性
        MessageProperties mqMsgProps = new MessageProperties();
        mqMsgProps.setExpiration(String.valueOf(RabbitMqConfig.RMQExpirationMillSecond));

        JsscMqMessage mqMessage = new JsscMqMessage();
        mqMessage.setHostId("java host01");
        mqMessage.setJobId(jobId);
        mqMessage.setOperationCode(JsscMqMessage.OPERCODE_QSJX_DISSOLVE);
        mqMessage.setOperationName("OPERCODE_QSJX_DISSOLVE");

        String jsonStr = JSON.toJSONString(mqMessage);
        Message message= new Message(jsonStr.getBytes(),mqMsgProps);
        //三个两个参数：交换机,路由键和消息体
        this.rabbitTemplate.convertAndSend(RabbitMqConfig.TOPIC_EXCHANGE_JSSC, RabbitMqConfig.JAVA2ARCPY_JSSC_ROUTINGKEY, message);

        String msgStr= String.format("---> java2arcpy sendMqQsjxDissolve,jobId: %s, mqContent: %s", jobId, mqMessage.toString());
        System.out.println();
        System.out.println(msgStr);
        log.info(msgStr);
    }

    /**
     * 地类还原--调用arcpy进行地类还原前的数据处理，包括图形几何修复、还原图斑筛选、用地红线扣除变化图斑等操作
     * @param jobId
     */
    public void sendMqDljyDataHandle(String jobId){
        //消息属性
        MessageProperties mqMsgProps = new MessageProperties();
        mqMsgProps.setExpiration(String.valueOf(RabbitMqConfig.RMQExpirationMillSecond));

        JsscMqMessage mqMessage = new JsscMqMessage();
        mqMessage.setHostId("java host01");
        mqMessage.setJobId(jobId);
        mqMessage.setOperationCode(JsscMqMessage.OPERCODE_DATA_HANDLE);
        mqMessage.setOperationName("OPERCODE_DATA_HANDLE");

        String jsonStr = JSON.toJSONString(mqMessage);
        Message message= new Message(jsonStr.getBytes(),mqMsgProps);
        //三个两个参数：交换机,路由键和消息体
        this.rabbitTemplate.convertAndSend(RabbitMqConfig.TOPIC_EXCHANGE_JSSC, RabbitMqConfig.JAVA2ARCPY_JSSC_ROUTINGKEY, message);

        String msgStr= String.format("--->java2arcpy sendMqDljyDataHandle,jobId: %s, mqContent: %s",jobId, mqMessage.toString());
        System.out.println();
        System.out.println(msgStr);
        log.info(msgStr);
    }

    /**
     * 地类还原--调用arcpy进行数据分析，包括地类图层融合、还原地类图层与权属界线的空间叠加、区县上传地类图层与还原地类图层的差异分析等
     * @param jobId
     */
    public void sendMqDlhyPostAnalyst(String jobId){
        //消息属性
        MessageProperties mqMsgProps = new MessageProperties();
        mqMsgProps.setExpiration(String.valueOf(RabbitMqConfig.RMQExpirationMillSecond));

        JsscMqMessage mqMessage = new JsscMqMessage();
        mqMessage.setHostId("java host01");
        mqMessage.setJobId(jobId);
        mqMessage.setOperationCode(JsscMqMessage.OPERCODE_DATA_ANALYST);
        mqMessage.setOperationName("OPERCODE_DATA_ANALYST");

        String jsonStr = JSON.toJSONString(mqMessage);
        Message message= new Message(jsonStr.getBytes(),mqMsgProps);
        //三个两个参数：交换机,路由键和消息体
        this.rabbitTemplate.convertAndSend(RabbitMqConfig.TOPIC_EXCHANGE_JSSC, RabbitMqConfig.JAVA2ARCPY_JSSC_ROUTINGKEY, message);

        String msgStr= String.format("---> java2arcpy sendMqDlhyPostAnalyst, jobId: %s, mqContent: %s", jobId, mqMessage.toString());
        System.out.println();
        System.out.println(msgStr);
        log.info(msgStr);
    }

    /**
     * 消息队列测试
     *
     * @param jobId
     * @param count
     */
    public void sendMqTest(String jobId,int count ){
        //int millSecond= 60*60;
        //消息属性
        MessageProperties mqMsgProps = new MessageProperties();
        mqMsgProps.setExpiration(String.valueOf(RabbitMqConfig.RMQExpirationMillSecond));

        System.out.println();
        System.out.println("--->sendMqTest,count:"+count);
        for (int i =0;i<count; i++) {
            MqMessage mqMessage = new MqMessage();

            mqMessage.setMsgId(String.format("msgId-%d",i+1));
            mqMessage.setHostId("java-host");
            mqMessage.setJobId(jobId);
            mqMessage.setJobStatus("test");
            mqMessage.setJobStatusCode(0);
            mqMessage.setModelName("jssc");
            mqMessage.setSubProcessName("dlhy");
            mqMessage.setMsgContent("ssssssssssssssssssssssss");
            mqMessage.setProcessValue(0);

            //JSONObject msg =  JSON.parseObject(JSON.toJSONString(mqMessage));
            String jsonStr = JSON.toJSONString(mqMessage);
            Message message= new Message(jsonStr.getBytes(),mqMsgProps);
            //三个两个参数：交换机,路由键和消息体
            this.rabbitTemplate.convertAndSend(RabbitMqConfig.TOPIC_EXCHANGE_JSSC, RabbitMqConfig.JAVA2ARCPY_JSSC_ROUTINGKEY, jsonStr);

            String msgStr= String.format("--->%d, jobId:%s, java mqMessage: %s",i+1, jobId, mqMessage.toString());
            System.out.println();
            System.out.println(msgStr);
            log.info(msgStr);
        }
    }


    /**
     * 筛选变化图斑中 BHDM=1 的图层并保存为一个新shp
     * @param inShppath  输入shp文件
     * @param outShpPath 输出新的shp文件
     * @return
     */
    public String selectBhtbAsNewShp(String inShppath, String outShpPath){
        String encoding = "GBK";
        String bhdmFieldName = "BHDM";
        String bhdmValue="1";

        String crsName = JTSGeometryWKTUtil.getShpCrsName(inShppath);
        String geoType = JTSGeometryWKTUtil.getShpType(inShppath);

        System.out.println("**************输入shp数据：" + inShppath);
        ShapefileDataStore shpDataStore = null;
        File file = new File(inShppath);
        try {
            String wkid = CrsUtil.getWkidByCrsName(crsName);

            URL url = file.toURI().toURL();
            shpDataStore = new ShapefileDataStore(url);
            shpDataStore.setCharset(Charset.forName(encoding));
            String typeName = shpDataStore.getTypeNames()[0];

            SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
            FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();
            //查询筛选
            Filter filter = (Filter) filterFactory.equals(filterFactory.property(bhdmFieldName), filterFactory.literal(bhdmValue));
            SimpleFeatureCollection featureCollection = featureSource.getFeatures(filter);

            List<StgeoFeature2> stgeoFeatureList = JTSGeometryWKTUtil.convertFeaCollection2StgeoFea(featureCollection,20);
            int size = stgeoFeatureList.size();
            System.out.println(String.format("--->BHDM=1, size: ",size));
            if( size>0 ) {
                String crs_wkt = CrsUtil.getWKT(wkid);
                JTSGeometryWKTUtil.saveFeatureCollectionAsNewSHP(featureCollection, outShpPath, crs_wkt);
            }

            shpDataStore.dispose();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return "";
    }

    /**
     * 筛选变化图斑中 BHDM=1 的图层并保存为一个新shp
     * @param inShppath
     * @return
     */
    public String selectBhtbAsGeoJsonStr(String inShppath){
        String encoding = "GBK";
        String bhdmFieldName = "BHDM";
        String bhdmValue="1";
        String geoJsonStr="";
        String crsName = JTSGeometryWKTUtil.getShpCrsName(inShppath);
        String geoType = JTSGeometryWKTUtil.getShpType(inShppath);

        System.out.println("**************输入shp数据：" + inShppath);
        ShapefileDataStore shpDataStore = null;
        File file = new File(inShppath);
        try {
            String wkid = CrsUtil.getWkidByCrsName(crsName);

            URL url = file.toURI().toURL();
            shpDataStore = new ShapefileDataStore(url);
            shpDataStore.setCharset(Charset.forName(encoding));
            String typeName = shpDataStore.getTypeNames()[0];

            SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
            FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();
            //筛选bhdm=1的图斑
            Filter filter = (Filter) filterFactory.equals(filterFactory.property(bhdmFieldName), filterFactory.literal(bhdmValue));
            SimpleFeatureCollection featureCollection = featureSource.getFeatures(filter);
            List<StgeoFeature2> stgeoFeatureList = JTSGeometryWKTUtil.convertFeaCollection2StgeoFea(featureCollection,20);
            int size = stgeoFeatureList.size();
            System.out.println(String.format("--->BHDM=1, size: ",size));
            if(size>0) {
                //转换为geojson
                geoJsonStr = JTSGeometryWKTUtil.stgeoFea2s2GeoJson(stgeoFeatureList, geoType, 20);
            }

            shpDataStore.dispose();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return geoJsonStr;
    }


    /**
     * 空间擦除操作，结果为geojson串
     *
     * @param ydhxfw_jsonStr  图层1-待擦除的图层
     * @param bhtb01_jsonStr  图层2-擦除范围图层
     * @return
     */
    public String diffBhtbAsJsonStr(String ydhxfw_jsonStr, String bhtb01_jsonStr){
        String encoding = "utf-8";
        String jsonStr="";
        GeoJson inputJson1= JSON.parseObject(ydhxfw_jsonStr,GeoJson.class);
        GeoJson inputJson2 = JSON.parseObject(bhtb01_jsonStr,GeoJson.class);
        try {
            jsonStr = JTSGeometryOperations.spatialDifference(inputJson1,inputJson2,encoding);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return jsonStr;
    }

    /**
     * 地类还原分析，结果保存到一个shp文件中,无返回值
     *
     * @param taskId   任务编号
     * @param dlhyFxlx  分析类型：bgdc或者dlhy
     * @param wkid  输入shp坐标信息的wkid
     * @param inShppath   输入shp文件
     * @param outShppath  输出shp文件
     */
    public void dlhyAnalyse(String taskId, String dlhyFxlx, int wkid, String inShppath, String outShppath) {

        //int wkid = 4524;
        Date dateNow = new Date();
        String dtimeNowStr = sdf.format(dateNow);
        System.out.println();
        System.out.println();
        System.out.println(String.format("************************************ dlhyAnalyse start, dlhyFxlx: %s  startDTime: %s ***********************************", dlhyFxlx, dtimeNowStr));
        System.out.println(String.format("--->taskId: %s ",taskId ));


        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(inShppath, wkid);
        GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.shp2GeoQuery(inShppath, wkid);
        DlhyAnalyseParam analyseParam = new DlhyAnalyseParam();
        analyseParam.setType(dlhyFxlx);
        analyseParam.setTaskId(taskId);
        analyseParam.setGeoJsonQuery(geoJsonQuery);
        analyseParam.setPhase(dtimeNowStr);

        int num = 0;
        List<DlhyEntity> dlhyEntities = new ArrayList<DlhyEntity>();
        List<CustomOverlay> cusOverlayList = null;

        //步骤5-地类还原
        if("dlhy".equalsIgnoreCase(dlhyFxlx)) {
            cusOverlayList = this.dlhyService.overlayDlhy("1111111111", analyseParam);
        }else if("bgdc".equalsIgnoreCase(dlhyFxlx)){
            cusOverlayList = this.dlhyService.overlayBgdc("1111111111", analyseParam);
        }
        for (CustomOverlay overlay : cusOverlayList) {
            //获取叠加的详细信息
            Map<String, List<DltbDetailResult>> detailResultsMap = (Map<String, List<DltbDetailResult>>) overlay.getOverlays_details();
            Set<String> keySet = detailResultsMap.keySet();
            Iterator<String> keyIter = keySet.iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();
                List<DltbDetailResult> detailResults = detailResultsMap.get(key);
                for (int i=0; i<detailResults.size(); i++) {
                    num++;
                    DltbDetailResult detailResult =detailResults.get(i);
                    String dkbh = detailResult.getTbbh();//地块编号
                    String dlbm = detailResult.getBm();//地类编码
                    String geomText = detailResult.getGeomText();//图形坐标串
                    double djmj = detailResult.getArea();//叠加面积

                    //String formatmsg = String.format("--->xh: %d, tbbh: %s, dlbm: %s, mj: %f, geomText: %s",num, dkbh, dlbm, djmj, geomText);
                    //System.out.println(formatmsg);

                    DlhyEntity dlhyEntity= new DlhyEntity();
                    dlhyEntity.setDkbh(dkbh);
                    dlhyEntity.setDlbm(dlbm);
                    dlhyEntity.setDjmj(djmj);
                    dlhyEntity.setGeomText(geomText);

                    dlhyEntities.add(dlhyEntity);
                }
            }
        }

        try {
            this.dlhyService.saveDlhyListAsNewSHP(taskId, wkid,dlhyEntities,outShppath);
        } catch (SchemaException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 地类还原分析，返回结果为 List<DlhyEntity> 对象中。
     *
     * @param taskId  任务编号
     * @param dlhyFxlx  类型：bgdc/dlhy/qxsb
     * @param wkid 投影系wkid
     * @param inShppath  输入的图形shp路径
     * @return
     */
    public  List<DlhyEntity> dlhyAnalyseEx(String taskId, String dlhyFxlx, int wkid, String inShppath) {
        //int wkid = 4524;
        Date startDTimeNow = new Date();
        String startDTimeStr = sdf.format(startDTimeNow);

        System.out.println();
        System.out.println();
        System.out.println(String.format("************************************ dlhyAnalyseEx start, dlhyFxlx: %s  startDTime: %s ***********************************", dlhyFxlx, startDTimeStr));
        System.out.println(String.format("--->taskId: %s ", taskId));
        String msgStr = String.format("--->dlhyAnalyseEx start, taskId: %s, dlhyFxlx: %s  startDTime: %s", taskId, dlhyFxlx, startDTimeStr);
        log.info(msgStr);

        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(inShppath, wkid);
        GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.shp2GeoQuery(inShppath, wkid);
        DlhyAnalyseParam dlhyParam = new DlhyAnalyseParam();
        dlhyParam.setType(dlhyFxlx);//地类还原分析类型
        dlhyParam.setTaskId(taskId);
        dlhyParam.setGeoJsonQuery(geoJsonQuery);
        dlhyParam.setPhase(startDTimeStr);

        //分析结果集合
        List<DlhyEntity> dlhyEntities = new ArrayList<DlhyEntity>();
        List<CustomOverlay> cusOverlayList = null;

        try {
            //分析方案
            String analyseProfileScheme = analyseConfig.getProfileScheme();

            //步骤5-地类还原
            if ("qxsb".equalsIgnoreCase(dlhyFxlx)) {
                cusOverlayList = this.dlhyService.overlayQxsb(taskId, dlhyParam);
            } else if ("dlhy".equalsIgnoreCase(dlhyFxlx)) {
                //按目标分析表的数量进行并行算
                cusOverlayList = this.dlhyService.overlayDlhy(taskId, dlhyParam);

                //按地块进行并行计算
                //cusOverlayList = this.dlhyService.overlayDlhyEx(taskId, dlhyParam);
            } else if ("bgdc".equalsIgnoreCase(dlhyFxlx)) {
                //按目标分析表的数量进行并行算
                cusOverlayList = this.dlhyService.overlayBgdc(taskId, dlhyParam);

                //按地块进行并行计算
                //cusOverlayList = this.dlhyService.overlayBgdcEx(taskId, dlhyParam);
            }
        } catch (Exception ex) {
            String errorMsg = String.format("--->overlayDlhy or overlayBgdc, taskId: %s, exception :%s ", taskId, ex.getMessage());
            System.out.println(errorMsg);
            log.info(errorMsg);
        }

        if (cusOverlayList == null) {
            String detailMsg = String.format("--->dlhyAnalyseEx failed, taskId: %s, dlhyFxlx: %s, cusOverlayList is null ", taskId, dlhyFxlx);
            System.out.println(detailMsg);
            log.info(detailMsg);

            return dlhyEntities;
        }

        int num = 0;
        for (CustomOverlay overlay : cusOverlayList) {
            //获取地类叠加分析的详细信息
            Map<String, List<DetailResult>> detailResultsMap = (Map<String, List<DetailResult>>) overlay.getOverlays_details();
            Set<String> keySet = detailResultsMap.keySet();
            Iterator<String> keyIter = keySet.iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();

                List<DetailResult> detailResults = detailResultsMap.get(key);
                int size = detailResults.size();
                System.out.println(String.format("--->detailResultsMap: %s, size：%d", key, size));
                for (int i = 0; i < size; i++) {
                    num++;

                    DetailResult detailResult = detailResults.get(i);
                    String dkbh = detailResult.getTbbh();//地块编号
                    String dlbm = detailResult.getBm();//地类编码
                    String dlmc = detailResult.getMc();//地类名称

                    String geomText = detailResult.getGeomText();//图形坐标串

                    double djMj = detailResult.getArea();//叠加相交的几何面积，单位平方米。
                    double tkMj = detailResult.getTkarea();//田坎面积
                    double kcMj = detailResult.getKcarea();//扣除面积，包含零星地物和线性地物
                    double kchMj = detailResult.getKcharea();//扣除后的净面积

                    //String formatMsg = String.format("--->xh: %d, tbbh: %s, dlbm: %s, djMj: %f, tkMj: %f, kcMj: %f, kchMj: %f, geomText: %s",num, dkbh, dlbm, djMj,tkMj,kcMj,kchMj, geomText);
                    //System.out.println(formatMsg);

                    DlhyEntity dlhyEntity = new DlhyEntity();
                    dlhyEntity.setDkbh(dkbh);
                    dlhyEntity.setDlbm(dlbm);
                    dlhyEntity.setDlmc(dlmc);
                    dlhyEntity.setFxlx(dlhyFxlx);//分析类型qxsb、bgdc、dlhy
                    //几何面积、田坎面积、扣除面积、扣除后净面积
                    dlhyEntity.setDjmj(djMj);
                    dlhyEntity.setTkmj(tkMj);
                    dlhyEntity.setKcmj(kcMj);
                    dlhyEntity.setKchmj(kchMj);
                    dlhyEntity.setGeomText(geomText);

                    dlhyEntities.add(dlhyEntity);
                }
            }
        }

        return dlhyEntities;
    }


    /**
     * 地类还原分析，返回结果封装为ResInfo对象。
     *
     * @param taskId  任务编号
     * @param dlhyFxlx  类型：bgdc/dlhy/qxsb
     * @param wkid 投影系wkid
     * @param inShppath  输入的图形shp路径
     * @return
     */
    public ResInfo dlhyAnalyseEx2(String taskId, String dlhyFxlx, int wkid, String inShppath) {
        ResInfo resInfo= null;
        //int wkid = 4524;
        Date startDTimeNow = new Date();
        String startDTimeStr = sdf.format(startDTimeNow);

        System.out.println();
        System.out.println();
        System.out.println(String.format("************************************ dlhyAnalyseEx2 start, dlhyFxlx: %s  startDTime: %s ***********************************", dlhyFxlx, startDTimeStr));
        System.out.println(String.format("--->taskId: %s ",taskId ));
        String msgStr = String.format("---> dlhyAnalyseEx2 start, taskId: %s, dlhyFxlx: %s,startDTime: %s", taskId, dlhyFxlx, startDTimeStr);
        log.info(msgStr);

        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(inShppath, wkid);
        GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.shp2GeoQuery(inShppath, wkid);
        DlhyAnalyseParam dlhyParam = new DlhyAnalyseParam();
        dlhyParam.setType(dlhyFxlx);//地类还原分析类型
        dlhyParam.setTaskId(taskId);
        dlhyParam.setGeoJsonQuery(geoJsonQuery);
        dlhyParam.setPhase(startDTimeStr);

        //分析结果集合
        List<DlhyEntity> dlhyEntities = new ArrayList<DlhyEntity>();
        List<CustomOverlay> successCusOverlayList = null;
        List<CustomOverlay> failureCusOverlayList = null;
        try {
            //分析方案
            String analyseProfileScheme = analyseConfig.getProfileScheme();

            //步骤5-地类还原
            if("qxsb".equalsIgnoreCase(dlhyFxlx)){
                List<CustomOverlay> cusOverlayList = this.dlhyService.overlayQxsb(taskId, dlhyParam);
                successCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==true).collect(Collectors.toList());
                failureCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==false).collect(Collectors.toList());
            } else if ("dlhy".equalsIgnoreCase(dlhyFxlx)) {
                //按目标分析表的数量进行并行算
                //cusOverlayList = this.dlhyService.overlayDlhy(taskId, dlhyParam);
                //按地块进行并行计算
                List<CustomOverlay> cusOverlayList = this.dlhyService.overlayDlhyEx(taskId, dlhyParam);
                successCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==true).collect(Collectors.toList());
                failureCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==false).collect(Collectors.toList());
            } else if ("bgdc".equalsIgnoreCase(dlhyFxlx)) {
                //按目标分析表的数量进行并行算
                //cusOverlayList = this.dlhyService.overlayBgdc(taskId, dlhyParam);
                //按地块进行并行计算
                List<CustomOverlay> cusOverlayList = this.dlhyService.overlayBgdcEx(taskId, dlhyParam);
                successCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==true).collect(Collectors.toList());
                failureCusOverlayList = cusOverlayList.stream().filter(v->v.isbSuccessed()==false).collect(Collectors.toList());
            }
        }catch (Exception ex){
            String errorMsg = String.format("--->overlayDlhy or overlayBgdc, taskId: %s, exception :%s ", taskId, ex.getMessage());
            System.out.println(errorMsg);
            log.info(errorMsg);
        }

        if(successCusOverlayList==null && failureCusOverlayList==null){
            String detailMsg = String.format("--->dlhyAnalyseEx2 failed, taskId: %s, dlhyFxlx: %s, cusOverlayList is null ",taskId, dlhyFxlx);
            System.out.println();
            log.info(detailMsg);

            resInfo = ResInfo.failed(detailMsg);
            resInfo.setData(dlhyEntities);
            return resInfo;
        }


        //第一部分：失败的地块
        StringBuilder failureSB = new StringBuilder();
        for (CustomOverlay overlay :  failureCusOverlayList) {
            String issueMsg = overlay.getIssueMessage();
            String dkbh= overlay.getDkbh();

            String detailOfDK = String.format("%s-%s",dkbh,issueMsg);
            failureSB.append(detailOfDK);
            failureSB.append(";");
        }
        String failureDetailMsg = failureSB.toString();

        //第二部分：成功的地块分析结果
        int num = 0;//序号
        for (CustomOverlay overlay : successCusOverlayList) {
            //获取地类叠加分析的详细信息
            Map<String, List<DetailResult>> detailResultsMap = (Map<String, List<DetailResult>>) overlay.getOverlays_details();
            Set<String> keySet = detailResultsMap.keySet();
            Iterator<String> keyIter = keySet.iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();

                List<DetailResult> detailResults = detailResultsMap.get(key);
                int size = detailResults.size();
                System.out.println(String.format("--->detailResultsMap: %s, size：%d",key, size));
                for (int i=0; i<size; i++) {
                    num++;

                    DetailResult detailResult = detailResults.get(i);
                    String dkbh = detailResult.getTbbh();//地块编号
                    String dlbm = detailResult.getBm();//地类编码
                    String dlmc = detailResult.getMc();//地类名称

                    String geomText = detailResult.getGeomText();//图形坐标串

                    double djMj = detailResult.getArea();//叠加相交的几何面积，单位平方米。
                    double tkMj = detailResult.getTkarea();//田坎面积
                    double kcMj = detailResult.getKcarea();//扣除面积，包含零星地物和线性地物
                    double kchMj = detailResult.getKcharea();//扣除后的净面积

                    //String formatMsg = String.format("--->xh: %d, tbbh: %s, dlbm: %s, djMj: %f, tkMj: %f, kcMj: %f, kchMj: %f, geomText: %s",num, dkbh, dlbm, djMj,tkMj,kcMj,kchMj, geomText);
                    //System.out.println(formatMsg);

                    DlhyEntity dlhyEntity = new DlhyEntity();
                    dlhyEntity.setDkbh(dkbh);
                    dlhyEntity.setDlbm(dlbm);
                    dlhyEntity.setDlmc(dlmc);
                    dlhyEntity.setFxlx(dlhyFxlx);//分析类型qxsb、bgdc、dlhy
                    //几何面积、田坎面积、扣除面积、扣除后净面积
                    dlhyEntity.setDjmj(djMj);
                    dlhyEntity.setTkmj(tkMj);
                    dlhyEntity.setKcmj(kcMj);
                    dlhyEntity.setKchmj(kchMj);
                    dlhyEntity.setGeomText(geomText);

                    dlhyEntities.add(dlhyEntity);
                }
            }
        }

        String finishedMsg = String.format("--->dlhyAnalyseEx2 finished , dlhyFxlx: %s, taskId: %s,success: %d, failure: %d", dlhyFxlx, taskId, successCusOverlayList.size(),failureCusOverlayList.size());
        System.out.println(finishedMsg);
        log.info(finishedMsg);

        resInfo = ResInfo.success(finishedMsg,dlhyEntities);
        resInfo.setRes(failureDetailMsg);

        return  resInfo;
    }


    /**
     * 地类还原分析,返回结果为list
     *
     * @param taskId   任务编号
     * @param dlhyFxlx  类型：bgdc/dlhy
     * @param wkid   投影系wkid
     * @param geoJson  输入的图形数据geojson
     * @return
     */
    public List<DlhyEntity> dlhyAnalyseExByGeoJson(String taskId, String dlhyFxlx, int wkid, String geoJson) {

        //int wkid = 4524;
        Date dateNow = new Date();
        String dtimeNowStr = sdf.format(dateNow);

        System.out.println();
        System.out.println();
        System.out.println(String.format("************************************ dlhyAnalyseExByGeoJson start, dlhyFxlx: %s  startDTime: %s ***********************************", dlhyFxlx, dtimeNowStr));
        System.out.println(String.format("--->taskId: %s ",taskId ));


        GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.geoJson2GeoQuery(geoJson, wkid);
        //GeoJsonQuery geoJsonQuery = GeoJsonQueryUtil.shp2GeoQuery(shppath, wkid);
        DlhyAnalyseParam analyseParam = new DlhyAnalyseParam();
        analyseParam.setType(dlhyFxlx);
        analyseParam.setTaskId(taskId);
        analyseParam.setGeoJsonQuery(geoJsonQuery);
        analyseParam.setPhase(dtimeNowStr);

        int num = 0;
        List<DlhyEntity> dlhyEntities = new ArrayList<DlhyEntity>();
        List<CustomOverlay> cusOverlayList = null;
        //步骤5-地类还原
        if("dlhy".equalsIgnoreCase(dlhyFxlx)) {
            cusOverlayList = this.dlhyService.overlayDlhy("1111111111", analyseParam);
        }else if("bgdc".equalsIgnoreCase(dlhyFxlx)){
            cusOverlayList = this.dlhyService.overlayBgdc("1111111111", analyseParam);
        }
        for (CustomOverlay overlay : cusOverlayList) {
            //获取叠加的详细信息
            Map<String, List<DltbDetailResult>> detailResultsMap = (Map<String, List<DltbDetailResult>>) overlay.getOverlays_details();
            Set<String> keySet = detailResultsMap.keySet();
            Iterator<String> keyIter = keySet.iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();
                List<DltbDetailResult> detailResults = detailResultsMap.get(key);
                for (int i=0; i<detailResults.size(); i++) {
                    num++;

                    DltbDetailResult detailResult =detailResults.get(i);
                    String dkbh = detailResult.getTbbh();//地块编号
                    String dlbm = detailResult.getBm();//地类编码
                    String dlmc = detailResult.getMc();//地类名称

                    String geomText = detailResult.getGeomText();//图形坐标串

                    double djjhMj = detailResult.getArea();//叠加相交的几何面积，单位平方米。
                    double tkMj = detailResult.getTkarea();//田坎面积
                    double kcMj = detailResult.getKcarea();//扣除面积，包含零星地物和线性地物
                    double kchMj = detailResult.getKcharea();//扣除后的净面积

                    //String formatmsg = String.format("--->xh: %d, tbbh: %s, dlbm: %s, mj: %f, geomText: %s",num, dkbh, dlbm, djjhMj, geomText);
                    //System.out.println(formatmsg);

                    DlhyEntity dlhyEntity= new DlhyEntity();
                    dlhyEntity.setDkbh(dkbh);
                    dlhyEntity.setDlbm(dlbm);
                    dlhyEntity.setDlmc(dlmc);
                    dlhyEntity.setFxlx(dlhyFxlx);

                    //几何面积、田坎面积、扣除面积、扣除后净面积
                    dlhyEntity.setDjmj(djjhMj);
                    dlhyEntity.setTkmj(tkMj);
                    dlhyEntity.setKcmj(kcMj);
                    dlhyEntity.setKchmj(kchMj);
                    dlhyEntity.setGeomText(geomText);

                    dlhyEntities.add(dlhyEntity);
                }
            }
        }

        return  dlhyEntities;
    }



}
